<?php

declare(strict_types=1);

namespace App\Third\Service\Kz;

use App\Activity\Model\ActivityGoodsModel;
use App\Common\Constants\ErrorCode;
use App\Common\Service\BaseService;
use App\Order\Model\EntrustOrderGoodsModel;
use App\Pay\Service\PayService;
use App\Resource\Model\GoodsModel;
use App\Resource\Model\ShopModel;
use App\Resource\Service\ShopService;
use App\Third\Service\Lsy\LsyShopGoodsPriceService;
use App\User\Service\MemberService;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\Logger\LoggerFactory;
use Psr\Log\LoggerInterface;

class KzMainService extends BaseService
{
    /**
     * 会员新增接口url
     */
    const ADD_CUSINFO_URL = '/kzPlatformOut/cusCtrl/addCusInfo';

    /**
     * 会员信息修改接口url
     */
    const UPDATE_CUSINFO_URL = '/kzPlatformOut/cusCtrl/updateCusInfo';

    /**
     * 会员信息查询接口url
     */
    const GET_CUSINFO_URL = '/kzPlatformOut/cusCtrl/getCusInfo';

    /**
     * 订单可用优惠券查询接口url
     */
    const QUERY_ORDER_TICKET_URL = '/kzPlatformOut/ticketCtrl/queryOrderTicket';

    /**
     * 订单支付接口url
     */
    const USE_TICKET_URL = '/kzPlatformOut/ticketCtrl/useTicket';

    /**
     * 支付撤销接口url
     */
    const CANCEL_ORDER_URL = '/kzPlatformOut/orderCtrl/cancelOrder';

    /**
     * 支付退款接口url
     */
    const REFUND_ORDER_URL = '/kzPlatformOut/orderCtrl/refundOrder';

    /**
     * 领取优惠-查询优惠活动列表url
     */
    const QUERY_ACTIVITY_LIST_URL = '/kzPlatformOut/receiveIntefaceCtrl/queryActivityListUrl';

    /**
     * 领取优惠-查询活动对应券或套餐列表url
     */
    const QUERY_TICKET_AND_PACKAGE_URL = '/kzPlatformOut/receiveIntefaceCtrl/queryTicketAndPackageUrl';

    /**
     * 领取优惠-开始领取url
     */
    const RECEIVE_PREFERENTIAL_URL = '/kzPlatformOut/receiveIntefaceCtrl/receivePreferentialUrl';

    /**
     * 优惠券-查询优惠券关联的门店信息
     */
    const QUERY_CUS_TICKET_SHOP_LIST_URL = '/kzPlatformOut/activityTicketCtrl/queryCusTicketShopListUrl';

    /**
     * 券列表
     */
    const RECEIVE_CENTER_KZ_CONPONS_LIST_URL = '/kzPlatformOut/ticketCtrl/queryTicketAndPackageForMall';

    /**
     * 订单可用优惠券查询接口
     */
    const QUERY_ORDER_TICKET = '/kzPlatformOut/ticketCtrl/queryOrderTicket';

    /**
     * 我的优惠券详情
     */
    const QUERY_CUS_TICKET_BY_F_TICKET_TYPE_URL = '/kzPlatformOut/activityTicketCtrl/queryCusTicketByfTicketTypeUrl';

    /**
     * 我的优惠券
     */
    const QUERY_CUS_TICKET_LIST_URL = '/kzPlatformOut/activityTicketCtrl/queryCusTicketListUrl';

    /**
     * 优惠券抵扣金额查询接口url
     */
    const QUERY_TICKET_DEDUCT_MONEY_URL = '/kzPlatformOut/ticketCtrl/queryTicketDeductMoney';

    /**
     * 会员消费汇总查询接口
     */
    const QUERY_SUMMARY_URL = 'kzPlatformOut/cusCtrl/queryAccountRecord';

    /**
     * 请求来源-客至提供
     */
    protected $resource;

    /**
     * 接口根地址
     * @var string
     */
    protected $baseUrl;

    /**
     * 商户编码-客至提供
     */
    protected $merchant_id;

    /**
     * 秘钥-客至提供
     */
    protected $secret_key;

    /**
     * http Client
     * @var
     */
    protected $httpClient;

    /**
     * Head头部鉴权参数
     * @var array
     */
    protected $headers = [];

    /**
     * @var LoggerInterface
     */
    protected $logger;


    /**
     * KzMainService constructor.
     * @param ClientFactory $clientFactory
     * @param LoggerFactory $loggerFactory
     */
    public function __construct(ClientFactory $clientFactory, LoggerFactory $loggerFactory)
    {
        parent::__construct();
        $this->logger = $loggerFactory->get('kzlog', 'kz');
        if (config('app_env') == 'dev') {
            //$this->baseUrl = 'http://49.4.78.164:8092';  //测试版
            $this->baseUrl = 'http://114.116.53.9:8093';  //测试版
            $this->secret_key = 'wKWuwyEIJ0LG3Taqmfy8meNYE62a8cHZ';
            $this->merchant_id = 'LSKZ';
            $this->resource = 'LSKZ';
        } else {
            $this->baseUrl = 'http://121.36.28.35:8092';  //最终版
            $this->secret_key = 'Z+qrpYnc9TgwqnAQ9p3yJVkVzMP1kSuv';
            $this->merchant_id = 'LSYLXP';
            $this->resource = 'LSYLXP';
        }
        $this->headers = [
            'resource' => $this->resource,
            'merchantId' => $this->merchant_id,
            'secretKey' => $this->secret_key
        ];
        $this->httpClient = $clientFactory->create(['base_uri' => $this->baseUrl, 'headers' => ['Content-Type' => 'text/plain'], 'timeout' => 30.0]);
    }


    /**
     * 查询客至会员信息
     * @param string $kzCusCode
     * @param null|string $phone
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getCusInfo(string $kzCusCode, ?string $phone = null)
    {
        $body = [
            'merchantId' => $this->merchant_id,
            'cusCode' => $kzCusCode,
            'phone' => $phone
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];
        try {
            $this->logger->info('客至会员信息查询接口请求参数', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::GET_CUSINFO_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if (($resContentsArr['retCode'] == 1) || empty($resContentsArr['cusInfo'])) {
                $resErrorMsg = $resContentsArr['resultMsg'] ?? '客至会员信息查询接口返回错误';
                $this->logger->debug('客至会员信息查询接口请求错误', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $this->logger->info('客至会员信息查询接口调用成功', ['response success' => $resContentsJson]);
        } catch (\Exception $e) {
            $this->logger->error('客至会员信息查询接口调用异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '客至会员信息查询接口调用异常'];
        }
        return ['code' => 1, 'msg' => '客至会员信息查询接口调用成功', 'data' => $resContentsArr ?? []];
    }

    /**
     * 会员新增接口
     * @param string $phone
     * @param string $cusName
     * @param string $shopCode
     * @param string $shopName
     * @param $gender
     * @param string $birthday
     * @param string $avatarAddr
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function addCusInfo(string $phone, string $cusName, string $shopCode, string $shopName, $gender, string $birthday, string $avatarAddr){
        $body     = [
            'merchantId' => $this->merchant_id,
            'phone'      => $phone,
            'cusName'    => $cusName,
            'shopCode'   => $shopCode,
            'shopName'   => $shopName,
            'gender'     => $gender,
            'birthday'   => $birthday,
            'avatarAddr' => $avatarAddr,
        ];
        $jsonBody = json_encode($body);
        $options  = [
            'headers' => $this->headers,
            'body'    => $jsonBody
        ];
        try {
            $this->logger->info('客至会员新增接口请求参数', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::ADD_CUSINFO_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if (!is_array($resContentsArr)) {
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '客至会员新增接口异常'];
            }
            if (($resContentsArr['retCode'] == 1) || !$resContentsArr['cusCode']) {
                $resErrorMsg = $resContentsArr['resultMsg'] ?? '客至会员新增接口返回错误';
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $this->logger->info('客至会员新增接口调用成功', ['response success' => $resContentsJson]);
        }catch (\Exception $e){
            $this->logger->error('客至会员新增接口调用异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '客至会员新增接口调用异常'];
        }
        return ['code' => 1, 'msg' => '客至会员新增接口调用成功', 'data' => ['cusCode' => $resContentsArr['cusCode']]];
    }

    /**
     * 会员充值消费汇总查询接口
     * @param string $cusCode
     * @param int $page
     * @param int $perpage
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function summary(string $cusCode, int $page, int $perpage){
        $body     = [
            'merchantId'  => $this->merchant_id,
            'fCusCode'     => $cusCode,
            'fAccountType'     => 1,
            'checkResource'     => 70,
            'pageNum'     => $page,
            'pageSize'     => $perpage,
            'resource'     => $this->resource,
        ];
        $jsonBody = json_encode($body);
        $options  = [
            'headers' => $this->headers,
            'body'    => $jsonBody
        ];
        try {
            $this->logger->info('查询会员账户操作记录传参', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::QUERY_SUMMARY_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if (!isset($resContentsArr['retCode']) || $resContentsArr['retCode']) {
                $resErrorMsg = $resContentsArr['msg'] ?? '查询会员账户操作记录返回错误';
                $this->logger->debug('查询会员账户操作记录返回异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $resData = [
                'cusCode' => $cusCode,
                'balanceMoney' => $resContentsArr['data']['fCusAccountBalance'] ?? [],
                'rows' => $resContentsArr['data']['rows'],
                'total' => $resContentsArr['data']['total'],
            ];
            $this->logger->info('查询会员账户操作记录成功', ['response success' => $resContentsJson]);
        }catch (\Exception $e){
            $this->logger->error('查询会员消费明细异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '查询会员消费明细异常'];
        }
        foreach($resData['rows'] as $k => $v){
            $resData['rows'][$k]['fValue'] = $v['fValue']/100;
        }
        return ['code' => 1, 'msg' => '消费汇总查询成功', 'data' => $resData];
    }


    /**
     * 客至退款(全部退/部分退)
     * @param string $cusCode
     * @param string $orderNumber
     * @param string $refundMoney
     * @param array $goodsList
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function refund(string $cusCode, string $orderNumber, string $refundMoney, array $goodsList)
    {
        $body = [
            'merchantId' => $this->merchant_id,    //商户号
            'cusCode' => $cusCode,              // 会员客至码
            'orderNumber' => $orderNumber,          // 订单号
            'refundMoney' => $refundMoney,          // 申请退款金额
            'goodsList' => $goodsList,            // 退款商品明细
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];
        try {
            $this->write('客至退款接口传参', $jsonBody);
            $httpResponse = $this->httpClient->post(self::REFUND_ORDER_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if (!isset($resContentsArr['retCode']) || $resContentsArr['retCode']) {
                $resErrorMsg = $resContentsArr['msg'] ?? '客至退款接口返回错误';
                $this->write('客至退款接口---' . $resErrorMsg, $resContentsJson);
                return [
                    'code' => 0,
                    'errorCode' => ErrorCode::SYSTEM_INVALID,
                    'throw' => "客至退款异常\n". __METHOD__ . ":line:".__LINE__."\n".
                        "订单编号[向下]\n{$orderNumber}\n".
                        "请求返回[向下]\n{$resErrorMsg}\n".
                        "请求参数[向下]\n{$jsonBody}",
                    'msg' => $resErrorMsg
                ];
            }
            $refundSubInfo = $resContentsArr['refundSubInfo'] ?? [];
            //余额本金，赠金
            $storePrincipalMoney = $resContentsArr['storePrincipalMoney'] ?? 0;
            $storeGrantsMoney = $resContentsArr['storeGrantsMoney'] ?? 0;
            $resData = [
                'refundMoney' => $refundMoney,
                'storePrincipalMoney' => $storePrincipalMoney,//本金
                'storeGrantsMoney' => $storeGrantsMoney, //赠金
                'refundSubInfo' => $refundSubInfo
            ];
            $this->write('客至退款接口调用成功', $resContentsJson);
        } catch (\Exception $e) {
            $msg = $e->getMessage();
            $line = $e->getLine();
            $this->write('客至退款接口调用失败', $msg);
            return [
                'code' => 0,
                'errorCode' => ErrorCode::SYSTEM_INVALID,
                'throw' => "客至退款异常\n". __METHOD__ . ":line:{$line}\n".
                    "订单编号[向下]\n{$orderNumber}\n".
                    "异常信息[向下]\n{$msg}\n".
                    "请求参数[向下]\n{$jsonBody}",
                'msg' => '退款失败'
            ];
        }
        return ['code' => 1, 'msg' => '客至退款接口调用成功', 'data' => $resData];
    }

    /**
     * 订单支付/核销优惠券
     * @param array $memberInfo
     * @param array $orderInfo
     * @param array $shopInfo
     * @param array $coupon
     * @param array $payInfo
     * @param array $goods
     * @param string $from
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function pay(array $memberInfo, array $orderInfo, array $shopInfo, array $coupon, array $payInfo, array $goods, string $from)
    {
        $body     = [
            'merchantId'    => $this->merchant_id,
            'cusCode'       => $memberInfo['kz_cus_code'],
            'cusName'       => $memberInfo['nickname'],
            'phone'         => $memberInfo['phone'],
            'orderNumber'   => $orderInfo['order_no'],
            'orderMoney'    => bcmul((string)$orderInfo['total_price'], '100'),
            'orderIntegral' => 0,
            'buildTime'     => date("YmdHis", strtotime($orderInfo['create_at'])),
            'payTime'       => date("YmdHis", time()),
            'orderResource' => 70,
            'goodsList'     => $goods,
            'payKey'        => $coupon['payKey'] ?? '',
            'freightFee'    => $orderInfo['freight_price'] * 100,
            'shopCode'      => env('APP_ENV') == 'dev' ? 777701 : $shopInfo['shop_no'],
            'shopName'      => $shopInfo['shop_name'],
            'deliveryType'  => $orderInfo['deal_type'] - 1,
            'paySubInfo'    => $payInfo
        ];
        $jsonBody = json_encode($body);
        $options  = [
            'headers' => $this->headers,
            'body'    => $jsonBody
        ];
        $payS = $this->container->get(PayService::class);
        try {
            if ($from == 'balance'){
                $info = '客至支付';
            }else{
                $info = '回调客至支付/核销券';
            }
            $payS->writeLog('info', $body, ['info' => $info . '传参'], 'pay');
            $httpResponse = $this->httpClient->post(self::USE_TICKET_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $resErrorMsg = $resContentsArr['msg'] ?? $info . '接口返回错误';
                $payS->writeLog('exception', $body, ['exception' => $info . '返回错误', 'response' => $resContentsArr], 'pay');
                return [
                    'code' => 0,
                    'errorCode' => ErrorCode::SYSTEM_INVALID,
                    'throw' => "{$info}异常\n".__METHOD__ . ":line:".__LINE__."\n".
                        "订单编号[向下]\n{$orderInfo['order_no']}\n".
                        "请求返回[向下]\n{$resContentsJson}\n".
                        "请求参数[向下]\n{$jsonBody}",
                    'msg' => $resErrorMsg
                ];
            }

            $payS->writeLog('info', $body, ['info' => $info . '成功响应', 'response' => $resContentsArr], 'pay');
        }catch (\Exception $e){
            $msg = $e->getMessage();
            $line = $e->getLine();
            $payS->writeLog('error', $body, ['error' => $info . '异常', 'errMsg' => $msg], 'pay');
            return [
                'code' => 0,
                'errorCode' => ErrorCode::SYSTEM_INVALID,
                'throw' => "{$info}异常\n".__METHOD__ . ":line:{$line}\n".
                    "订单编号[向下]\n{$orderInfo['order_no']}\n".
                    "异常信息[向下]\n{$msg}\n".
                    "请求参数[向下]\n{$jsonBody}",
                'msg' => '订单支付接口异常'
            ];
        }
        return [
            'code' => 1,
            'msg' => '客至支付成功',
            'data' => [
                'ticketRefundInfo' => $resContentsArr['ticketRefundInfo'] ?? [],//用券,
                'storePrincipalMoney' => $resContentsArr['storePrincipalMoney'] ?? 0,//本金 单位 分,
                'storeGrantsMoney' => $resContentsArr['storeGrantsMoney'] ?? 0 //赠金 单位 分
            ]
        ];
    }

    /**
     * 会员优惠券查询接口
     * @param string $fCusCode
     * @param int $fType
     * @param int $page
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function memberCouponsByCusInfo(string $fCusCode, int $fType, int $page, int $pageSize){
        $body = [
            'merchantId' => $this->merchant_id,
            'fCusCode' => $fCusCode,
            'page' => $page,
            'pageSize' => $pageSize,
            'fType' => $fType
        ];
        $jsonBody = json_encode($body);
        $options  = [
            'headers' => $this->headers,
            'body'    => $jsonBody
        ];
        try {
            $this->write('会员优惠券查询接口传参', $jsonBody);
            $httpResponse = $this->httpClient->post(self::QUERY_CUS_TICKET_LIST_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $this->write('会员优惠券查询接口返回错误', $resContentsJson);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => "优惠券查询接口返回错误--{$resContentsArr['resultMsg']}"];
            }
            $ticketList = $resContentsArr['ticketList'] ?? [];
            $ticket = [];
            if (!empty($ticketList)){
                foreach ($ticketList as $k => $v){
                    $ticket[$k]['name'] = $v['fName'];
                    $ticket[$k]['category'] = $v['fType'];
                    $ticket[$k]['scope'] = $v['fUseRange'];
                    $ticket[$k]['apply_type'] = $v['fUseType'];
                    $ticket[$k]['expire'] = empty($v['fStartTime']) ? '' : $v['fStartTime']. ' - '. $v['fEndTime'];
                    $ticket[$k]['effective_day'] = $v['fDays'];
                    $ticket[$k]['number'] = $v['ticketCount'];
                    $ticket[$k]['value'] = bcmul((string)$v['fMoney'], '100');
                    $ticket[$k]['ticket_code'] = $v['fTicketCode'];
                    $ticket[$k]['subcode'] = $v['fId'];
                }
            }

            $this->write('会员优惠券查询接口返回', $resContentsJson);
        }catch (\Exception $e){
            $this->write('会员优惠券查询异常', $e->getMessage());
            return ['code' => 0,'errorCode' => ErrorCode::SYSTEM_INVALID,'msg' => '会员优惠券查询异常'];
        }
        return ['code' => 1, 'msg' => '会员优惠券查询成功', 'data' => $ticket];
    }

    /**
     * 查询优惠活动列表
     * @param string $fState
     * @param string $isEffect
     * @param string $fActivityName
     * @param int $page
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function queryActivityList(string $fState,string $isEffect, string $fActivityName, int $page, int $pageSize)
    {
        $body = [
            'merchantId' => $this->merchant_id,
            'page' => $page,
            'pageSize' => $pageSize,
            'fState' => $fState,
            'isEffect' => $isEffect,
            'fActivityName' => $fActivityName
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];
        try {
            $this->logger->info('查询优惠活动列表接口传参：', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::QUERY_ACTIVITY_LIST_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $resErrorMsg = $resContentsArr['msg'] ?? '查询优惠活动列表接口返回错误';
                $this->logger->debug('查询优惠活动列表接口异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $this->logger->info('查询优惠活动列表接口返回：', ['response success' => $resContentsJson]);
        }catch (\Exception $e){
            $this->logger->error('查询优惠活动列表接口异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '查询优惠活动列表接口异常'];
        }
        return [
            'code' => 1,
            'msg' => '查询优惠活动列表成功',
            'data' => [
                'activityInfo' => $resContentsArr['activityInfo'],
                'total' => $resContentsArr['total']
            ]
        ];
    }

    /**
     * 查询活动对应券或套餐列表
     * @param string $activity_id
     * @param string $fCusCode
     * @param int $page
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function queryTicketAndPackage(string $activity_id, string $fCusCode, int $page = 1, int $pageSize = 10)
    {
        $body = [
            'merchantId' => $this->merchant_id,
            'page' => $page,
            'pageSize' => $pageSize,
            'fActivityId' => $activity_id,
            'fCusCode' => $fCusCode
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];

        try {
            $this->logger->info('查询活动对应券或套餐列表接口传参：', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::QUERY_TICKET_AND_PACKAGE_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $resErrorMsg = $resContentsArr['msg'] ?? '查询活动对应券或套餐列表接口返回错误';
                $this->logger->debug('查询活动对应券或套餐列表接口异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $this->logger->info('查询活动对应券或套餐列表接口返回：', ['response success' => $resContentsJson]);
        }catch (\Exception $e){
            $this->logger->error('查询活动对应券或套餐列表接口异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '查询优惠活动列表接口异常'];
        }
        return [
            'code' => 1,
            'msg' => '查询活动对应券或套餐列表成功',
            'data' => [
                'activityInfo' => $resContentsArr['drawCouponInfo'],
                'total' => $resContentsArr['total'],
                'fIsGrade' => $resContentsArr['fIsGrade']
            ]
        ];
    }

    /**
     * 领劵中心-优惠券列表
     * @param string $shopCode
     * @param int $couponType
     * @param string $goodsId
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function receiveCenterKzCouponList(string $shopCode, int $couponType, int $pageNum, int $pageSize){
        $body = [
            'merchantId' => $this->merchant_id,
            'shopCode' => $shopCode,
            'couponType' => $couponType,
            'goodsId' => 0,
            'pageNum' => $pageNum,
            'pageSize' => $pageSize
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];

        try {
            $this->logger->info('领劵中心-优惠券列表传参：', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::RECEIVE_CENTER_KZ_CONPONS_LIST_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $resErrorMsg = $resContentsArr['msg'] ?? '领劵中心-优惠券列表返回错误';
                $this->logger->debug('领劵中心-优惠券列表查询异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $this->logger->info('领劵中心-优惠券列表返回：', ['response success' => $resContentsJson]);
        }catch (\Exception $e){
            $this->logger->error('领劵中心-优惠券列表接口异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '领劵中心-优惠券列表接口异常'];
        }
        return ['code' => 1, 'msg' => '领劵中心-优惠券列表调用成功', 'data' => $resContentsArr];
    }

    /**
     * 优惠券详情
     * @param string $fCusCode
     * @param string $fTicketType
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function kzCouponsDetail(string $fCusCode, string $fTicketType){
        $body = [
            'merchantId' => $this->merchant_id,
            'fCusCode' => $fCusCode,
            'fTicketType' => $fTicketType
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];

        try {
            $this->logger->info('优惠券详情接口传参', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::QUERY_CUS_TICKET_BY_F_TICKET_TYPE_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $this->logger->debug('优惠券详情接口查询异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '优惠券不存在'];
            }
            $detail = $resContentsArr['cusTicketDetail'];
            $detail = [
                'name' => $detail['fName'],
                'category' => $detail['fType'],
                'scope' => $detail['fUseRange'],
                'apply_type' => $detail['fUseType'],
                'expire' => empty($detail['fStartTime']) ? '' : $detail['fStartTime']. ' - '. $detail['fEndTime'],
                'effective_day' => $detail['fDays'],
                'value' => bcmul((string)$detail['fMoney'],'100'),
                'number' => $detail['ticketCount'],
                'minimum_amt' => bcmul((string)$detail['fLowMoney'],'100'),
                'use_time' => $detail['fUseTime'],
                'limit_use_number' => $detail['fLimitNum'],
                'usable' => $detail['fEffectDays'],
                'subcode' => $detail['fId'],
                'content' => $detail['fContent']
            ];
            $this->logger->info('优惠券详情接口返回', ['response success' => $resContentsJson]);
        } catch (\Exception $e) {
            $this->logger->error('优惠券详情接口异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '优惠券详情接口异常'];
        }
        return ['code' => 1, 'msg' => '优惠券详情接口调用成功', 'data' => $detail];
    }

    /**
     * @param string $fCusCode
     * @param string $fTicketType
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function queryAvailableStoresList(string $fCusCode, string $fTicketType){
        $body = [
            'merchantId' => $this->merchant_id,
            'fCusCode' => $fCusCode,
            'fTicketType' => $fTicketType
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];

        try {
            $this->logger->info('优惠券可用门店接口传参', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::QUERY_CUS_TICKET_SHOP_LIST_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            $this->logger->info('优惠券可用门店接口返回结果', ['response success' => $resContentsJson]);
            // 店铺编码 ==> 店铺信息
            if (isset($resContentsArr['shopList']) && !empty($resContentsArr['shopList'])){
                $shopNoArr = array_column($resContentsArr['shopList'], 'fShopCode');
                $shopList = ShopModel::query()
                    ->whereIn('shop_id',$shopNoArr)
                    ->where('is_deleted', 0)
                    ->select(['shop_name','address','start_time','end_time'])
                    ->get();
            }else{
                $shopList = ShopModel::query()
                    ->where('is_deleted', 0)
                    ->select(['shop_name','address','start_time','end_time'])
                    ->get();
            }
        } catch (\Exception $e) {
            $this->logger->error('优惠券可用门店接口异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '优惠券可用门店接口异常'];
        }

        return ['code' => 1, 'msg' => '优惠券可用门店接口调用成功', 'data' => $shopList];
    }

    /**
     * 商品详情---适用券列表
     * @param string $shopCode
     * @param int $couponType
     * @param string $goodsId
     * @param string $typeId
     * @param string $brandId
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function queryTicketForGoods(string $shopCode, int $couponType, string $goodsId, string $typeId, string $brandId, int $pageNum, int $pageSize){
        $body = [
            'merchantId' => $this->merchant_id,
            'shopCode' => $shopCode,
            'couponType' => $couponType,
            'goodsId' => $goodsId,
            'brandId' => $brandId,
            'typeId' => $typeId,
            'pageNum' => $pageNum,
            'pageSize' => $pageSize
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];

        try {
            $this->logger->info('商品适用券传参：', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::RECEIVE_CENTER_KZ_CONPONS_LIST_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $resErrorMsg = $resContentsArr['msg'] ?? '商品适用券返回异常';
                $this->logger->debug('商品适用券返回异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }

            $list = $this->transformData($resContentsArr['ticketInfo']);

            $this->logger->info('商品适用券查询成功', ['response success' => $resContentsJson]);
        }catch (\Exception $e){
            $this->logger->error('商品适用券接口异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '商品适用券接口异常'.$e->getMessage()];
        }
        return ['code' => 1, 'msg' => '商品适用券接口调用成功', 'data' => ['list' => $list, 'count' => $resContentsArr['count']]];
    }


    /**
     * 订单下可使用优惠券列表查询
     * @param string $kzCusCode
     * @param string $shopCode
     * @param string $freightFee
     * @param string $orderGoodsMoney
     * @param string $orderIntegral
     * @param string $buildTime
     * @param array $goods
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function orderCouponList(string $kzCusCode,string $shopCode,string $freightFee,string $orderGoodsMoney,string $orderIntegral,array $goods){
        $body = [
            'merchantId' => $this->merchant_id,
            'fAppCode' => 'YLXPMINPROGRAN',
            'cusCode' => $kzCusCode,
            'shopCode' => $shopCode,
            'orderMoney' => $orderGoodsMoney,
            'orderIntegral' => $orderIntegral,
            'buildTime' => date('YmdHis'),
            'freightFee' => $freightFee,
            'fMerSource' => 0,      // 0分， 1元
            'goodsList' => $goods
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];

        try {
            $this->write('订单可用优惠券查询传参', $jsonBody);
            //$this->logger->info('订单可用优惠券查询传参：', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::QUERY_ORDER_TICKET, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $resErrorMsg = $resContentsArr['msg'] ?? '订单可用优惠券查询返回异常';
                $this->logger->debug('订单可用优惠券查询返回异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }

            $ticketList = $resContentsArr['ticketInfo'] ?? [];
            if (!empty($ticketList)){
                $resContentsArr['ticketInfo'] = $this->transform($resContentsArr['ticketInfo'], null);
            }

            //$this->logger->info('订单可用优惠券查询成功', ['response success' => $jsonBody]);
            $this->write('订单可用优惠券查询成功返回', $resContentsJson);
        } catch (\Exception $e) {
            $this->write('订单可用优惠券查询返回异常', $e->getMessage());
            //$this->logger->error('订单可用优惠券查询返回异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '订单可用优惠券查询返回异常-'.$e->getMessage()];
        }
        return ['code' => 1, 'msg' => '订单可用优惠券查询成功', 'data' => $resContentsArr];
    }

    /**
     * 订单使用优惠券
     * @param string $kzCusCode
     * @param string $shopCode
     * @param string $freightFee
     * @param string $orderGoodsMoney
     * @param array $couponArr
     * @param int $usePayType
     * @param array $goods
     * @param $payKey
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function queryTicketDeductMoney(string $kzCusCode,string $shopCode,string $freightFee,string $orderGoodsMoney,array $couponArr,int $usePayType,array $goods,$payKey)
    {
        $body = [
            'merchantId' => $this->merchant_id,
            'cusCode' => $kzCusCode,
            'shopCode' => $shopCode,
            'orderMoney' => $orderGoodsMoney,
            'ticketDeductType' => $couponArr['ticketDeductType'],
            'ticketTypeCode' => $couponArr['ticketTypeCode'],
            'ticketCode' => $couponArr['ticket_code'],
            'ticketType' => $couponArr['ticketType'],
            'payKey' => $payKey,
            'usePayType' => $usePayType,
            'freightFee' => $freightFee,
            'fMerSource' => 1,
            'goodsList' => $goods
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];
        try {
            $this->write('优惠券抵扣金额查询接口传参', $jsonBody);
            $httpResponse = $this->httpClient->post(self::QUERY_TICKET_DEDUCT_MONEY_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1 || empty($resContentsArr['payKey'])) {
                $resErrorMsg = $resContentsArr['msg'] ?? '客至优惠券抵扣金额查询返回错误';
                $this->write('优惠券抵扣金额查询返回错误', $resContentsJson);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $this->write('优惠券抵扣金额查询成功返回', $resContentsJson);
        }catch (\Exception $e){
            $this->write('优惠券抵扣金额查询接口异常', $e->getMessage());
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '优惠券抵扣金额查询异常-'.$e->getMessage()];
        }
        return ['code' => 1, 'msg' => '优惠券抵扣金额查询成功', 'data' => [
            'deductMoney' => bcmul((string)$resContentsArr['deductMoney'], '100'), // 转换为分
            'payKey' => $resContentsArr['payKey'],
            'canUseticketInfo' =>$resContentsArr['canUseticketInfo'],
            'noUseticketInfo' =>$resContentsArr['noUseticketInfo'],
            'surplusTicketInfo' =>$resContentsArr['surplusTicketInfo']
        ]];
    }


    /**
     * 领券中心/商品下可用优惠券
     * @param int $mid
     * @param string $shopId
     * @param int $couponType
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function couponCenter(int $mid, string $shopId, int $couponType, int $pageNum, int $pageSize){
        $cusCode = $this->container->get(MemberService::class)->findValue(['mid' => $mid], 'kz_cus_code');
        $shop = $this->container->get(ShopService::class)->shopInfoByWhere(['shop_id' => $shopId], ['shop_no']);
        $res = $this->receiveCenterKzCouponList((string)$shop['shop_no'], $couponType, $pageNum, $pageSize);
        if ($res['code'] == 0) return $res;
        if ($res['data']['count'] > 0){
            $filter = ['新人', '年度账单分享礼'];
            $res = $this->filterAppointCoupon($cusCode, $res, $filter);
        }
        $list = $this->transformData($res['data']['ticketInfo']);
        return ['code' => 1, 'msg' => '领券中心', 'data' => ['list' => $list, 'count' => $res['data']['count']]];
    }


    /**
     * 过滤特定优惠券 待优化
     * @param $cusCode
     * @param $ticket
     * @param array $filter
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function filterAppointCoupon($cusCode, $ticket, array $filter){
        $coupon = [];
        foreach ($filter as $kk => $act_name){
            $list = $this->queryActivityList('1', '1', $act_name, 1, 999);
            if (!empty($list['data']['activityInfo']) && isset($list['data']['activityInfo'])){
                $_fActivityId = array_column($list['data']['activityInfo'],'fActivityId');
                foreach ($_fActivityId as $k => $fActivityId){
                    $ret = $this->queryTicketAndPackage($fActivityId, $cusCode, 1, 999); //活动下优惠券
                    $coupon = array_merge($ret['data']['activityInfo'], $coupon);
                }
            }
        }
        $filterCouponCodeArr = array_column($coupon,'fCouponCode');
        foreach ($ticket['data']['ticketInfo'] as $k => $v){
            if (in_array($v['fCouponCode'], $filterCouponCodeArr)){
                unset($ticket['data']['ticketInfo'][$k]);
                $ticket['data']['count']--;
            }
        }
        $ticket['data']['ticketInfo'] = array_values($ticket['data']['ticketInfo']);
        return $ticket;
    }

    /**
     * 领取优惠-开始领取
     * @param object $member
     * @param array $shop
     * @param string $fActivityId
     * @param string $fDrawCouponId
     * @param string $fCouponCode
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function receiveCoupon(object $member, array $shop, string $fActivityId, string $fDrawCouponId, string $fCouponCode){
        $body = [
            'merchantId' => $this->merchant_id,
            'fCusCode' => $member->kz_cus_code,
            'fActivityId' => $fActivityId,
            'fCusName' => $member->nickname,
            'fCusPhone' => $member->phone,
            'fShopCode' => $shop['shop_no'],
            'fShopName' => $shop['shop_name'],
            'fDrawCouponId' => $fDrawCouponId,
            'fCouponCode' => $fCouponCode
        ];
        $jsonBody = json_encode($body);
        $options = [
            'headers' => $this->headers,
            'body' => $jsonBody
        ];

        try {
            $this->logger->info('领取优惠接口传参：', ['request' => $jsonBody]);
            $httpResponse = $this->httpClient->post(self::RECEIVE_PREFERENTIAL_URL, $options);
            $resContentsJson = $httpResponse->getBody()->getContents();
            $resContentsArr = json_decode($resContentsJson, true);
            if ($resContentsArr['retCode'] == 1) {
                $resErrorMsg = $resContentsArr['msg'] ?? '领取优惠接口异常';
                $this->logger->debug('领取优惠接口返回异常', ['response error' => $resContentsJson]);
                return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $resErrorMsg];
            }
            $this->logger->info('领取优惠接口返回', ['response success' => $resContentsJson]);
        } catch (\Exception $e) {
            $this->logger->error('领取优惠接口异常', ['error' => $e->getMessage()]);
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '领取优惠券接口异常'.$e->getMessage()];
        }
        return ['code' => 1, 'msg' => '领取优惠券成功', 'data' => $resContentsArr];
    }

    /**
     * 领取优惠券
     * @param int $mid
     * @param string $shop_id
     * @param string $coupon_activity_id
     * @param string $draw_coupon_id
     * @param string $subcode
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function receiveCouponDo(int $mid, string $shop_id, string $coupon_activity_id, string $draw_coupon_id, string $subcode){
        $member = $this->container->get(MemberService::class)->findFirst(['mid' => $mid], ['kz_cus_code','nickname','phone']);
        $shop = $this->container->get(ShopService::class)->shopInfoByWhere(['shop_id' => $shop_id], ['shop_no','shop_name']);
        return $this->receiveCoupon($member, $shop, $coupon_activity_id, $draw_coupon_id, $subcode);
    }

    /**
     * 优惠券详情
     * @param int $mid
     * @param string $subcode
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getCouponDetail(int $mid, string $subcode){
        $cusCode = $this->container->get(MemberService::class)->findValue(['mid' => $mid], 'kz_cus_code');
        return $this->kzCouponsDetail($cusCode, $subcode);
    }

    /**
     * 优惠券可用门店
     * @param int $mid
     * @param string $subcode
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getStores(int $mid, string $subcode){
        $cusCode = $this->container->get(MemberService::class)->findValue(['mid' => $mid], 'kz_cus_code');
        return $this->queryAvailableStoresList($cusCode, $subcode);
    }

    /**
     * 商品，品牌，类别可用优惠券
     * @param string $shopId
     * @param int $couponType
     * @param string $goodsId
     * @param string $typeId
     * @param string $brandId
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getGoodsCouponList(string $shopId, int $couponType, string $goodsId, string $typeId, string $brandId, int $pageNum, int $pageSize){
        $shop = $this->container->get(ShopService::class)->shopInfoByWhere(['shop_id' => $shopId], ['shop_no']);
        return $this->queryTicketForGoods((string)$shop['shop_no'], $couponType, $goodsId, $typeId, $brandId, $pageNum, $pageSize);
    }

    /**
     * 订单可用优惠券
     * @param int $mid
     * @param string $shopId
     * @param string $orderIntegral
     * @param string $freightFee
     * @param array $goodsListArr
     * @param $orderSource
     * @param $entrustId
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getOrderCouponList(int $mid, string $shopId, string $orderIntegral, string $freightFee, array $goodsListArr, $orderSource, $entrustId){
        $cusCode = (string)$this->container->get(MemberService::class)->findValue(['mid' => $mid], 'kz_cus_code');
        $shop = $this->container->get(ShopService::class)->shopInfoByWhere(['shop_id' => $shopId], ['shop_no','lsy_shop_no']);
        if (is_numeric($entrustId)){
            $extInfo = $this->entrustOrder($entrustId);
        }else{
            $extInfo = $this->getGoodsInfo($goodsListArr, (string)$shop['lsy_shop_no'], $orderSource);
        }

        $gInfo = $this->transformGoodsDataPushKz($goodsListArr, $extInfo, $entrustId);

        $orderGoodsMoney = (string)array_sum($gInfo['amount']);
        $freightFee = bcmul($freightFee, '100');
        return $this->orderCouponList($cusCode, (string)$shop['shop_no'], $freightFee, $orderGoodsMoney, $orderIntegral, $gInfo['goods']);
    }

    /**
     * 订单使用优惠券
     * @param int $mid
     * @param string $shopId
     * @param array $goodsListArr
     * @param array $couponArr
     * @param int $usePayType
     * @param string $freightFee
     * @param $payKey
     * @param $orderSource
     * @param $entrustId
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function useCouponDo(int $mid, string $shopId, array $goodsListArr, array $couponArr, int $usePayType, string $freightFee, $payKey,$orderSource,$entrustId){
        $cusCode = $this->container->get(MemberService::class)->findValue(['mid' => $mid], 'kz_cus_code');
        $shop = $this->container->get(ShopService::class)->shopInfoByWhere(['shop_id' => $shopId], ['shop_no','lsy_shop_no']);
        if (is_numeric($entrustId)){
            $extInfo = $this->entrustOrder($entrustId);
        }else{
            $extInfo = $this->getGoodsInfo($goodsListArr, (string)$shop['lsy_shop_no'], $orderSource);
        }

        // 优惠券信息
        $couponInfo = $this->kzCouponsDetail($cusCode, $couponArr['subcode']);
        if ($couponInfo['code'] == 0) return $couponInfo;
        $couponArr['ticketDeductType'] = $couponInfo['data']['category'];
        $couponArr['ticketType'] = $couponInfo['data']['apply_type'];
        $couponArr['ticketTypeCode'] = $couponInfo['data']['subcode'];

        $redis = $this->redis;

        $gInfo = $this->transformGoodsDataPushKz($goodsListArr, $extInfo, $entrustId);

        $couponDeductedMoney = $redis->get($payKey);
        $couponDeductedMoney = $couponDeductedMoney !== false  ? $couponDeductedMoney : (string)array_sum($gInfo['amount']);
        $freightFee = bcmul($freightFee,'100');

        $ret = $this->queryTicketDeductMoney($cusCode, (string)$shop['shop_no'], $freightFee, $couponDeductedMoney, $couponArr, $usePayType, $gInfo['goods'], $payKey);
        if ($ret['code'] == 0) return $ret;

        $couponDeductedMoney = bcsub($couponDeductedMoney, $ret['data']['deductMoney']);

        if ($usePayType == 2 and count($ret['data']['canUseticketInfo']) == 1){
            $couponInfo = $this->kzCouponsDetail($cusCode, $ret['data']['canUseticketInfo'][0]['ticketTypeCode']);
        }

        $ret['data']['canUseticketInfo'] = $this->transform($ret['data']['canUseticketInfo'], $couponInfo['data']);
        $ret['data']['noUseticketInfo'] = $this->transform($ret['data']['noUseticketInfo'], null);
        $ret['data']['surplusTicketInfo'] = $this->transform($ret['data']['surplusTicketInfo'], null);
        $ret['data'] = array_merge(['coupon_deducted_money' => $couponDeductedMoney], $ret['data']);

        $redis->set($payKey, $couponDeductedMoney);
        $redis->expire($payKey,7200);
        return $ret;
    }

    /**
     * 新人优惠券
     * @param int $mid
     * @param string $isEffect
     * @param string $fState
     * @param string $fActivityName
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function newcomerCoupon(int $mid, string $isEffect, string $fState, string $fActivityName, int $pageNum, int $pageSize){
        $cusCode = $this->container->get(MemberService::class)->findValue(['mid' => $mid], 'kz_cus_code');
        $list = $this->queryActivityList( $fState, $isEffect, $fActivityName, $pageNum, $pageSize);
        if ($list['code'] == 0) {
            return $list;
        } else {
            if ( isset($list['data']['activityInfo']) && !empty($list['data']['activityInfo'])) {
                $_fActivityId = array_column($list['data']['activityInfo'], 'fActivityId');
                list($coupon, $total) = [[], []];
                foreach ($_fActivityId as $k => $fActivityId){
                    $res = $this->queryTicketAndPackage($fActivityId, $cusCode, $pageNum, $pageSize); //活动下优惠券
                    $ticket = array_map(fn($v) => $v + ['fActivityId' => $fActivityId], $res['data']['activityInfo']);
                    array_push($total, $res['data']['total']);
                    $coupon = array_merge($ticket, $coupon);
                }
                $list = $this->transformData($coupon);
                return ['code' => 1, 'msg' => '新人优惠券查询成功', 'data' => ['list' => $list, 'total' => array_sum($total)]];
            }
            return ['code' => 1, 'msg' => '新人优惠券查询成功', 'data' => null];
        }
    }

    /**
     * 新人一键领取优惠券
     * @param int $mid
     * @param string $shopId
     * @param array $couponsArr
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function batchCollectNewcomerCoupon(int $mid, string $shopId, array $couponsArr){
        $member = $this->container->get(MemberService::class)->findFirst(['mid' => $mid], ['kz_cus_code','nickname','phone','new_receive_status']);
        $shop = $this->container->get(ShopService::class)->shopInfoByWhere(['shop_id' => $shopId], ['shop_no','shop_name']);
        foreach ($couponsArr as $k => $v){
            $res = $this->receiveCoupon($member, $shop, $v['coupon_activity_id'], (string)$v['draw_coupon_id'], $v['subcode']);
        }
        if ($res['code'] == 0) {
            return $res;
        } else {
            // 领取新人优惠券后入库已领取标识
            $member->new_receive_status = 1;
            $member->save();
            return ['code' => 1, 'msg' => '领取成功', 'data' => $res['data']];
        }
    }

    /**
     * @param string $isEffect
     * @param string $fState
     * @param string $fActivityName
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function newcomerActivityRule(string $isEffect, string $fState, string $fActivityName, int $pageNum, int $pageSize){
        $list = $this->queryActivityList($fState, $isEffect, $fActivityName, $pageNum, $pageSize);
        if ($list['code'] == 0) {
            return $list;
        } else {
            if(!empty($list['data']['activityInfo'])){
                $data = [
                    'start_time' => $list['data']['activityInfo'][0]['fBeginTime'] ?? '',
                    'end_time' => $list['data']['activityInfo'][0]['fEndTime'] ?? '',
                    'content' => $list['data']['activityInfo'][0]['fDrawDesc'] ?? ''
                ];
            }
            return ['code' => 1, 'msg' => '查询成功', 'data' => $data ?? []];
        }
    }


    /**
     * 批量领取年度账单分享礼 优惠券
     * 需第三方提供 一键领取券包的接口
     * @param int $mid
     * @param string $shopId
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function yearBillGiveCoupon(int $mid, string $shopId){
        $member = $this->container->get(MemberService::class)->findFirst(['mid' => $mid], ['kz_cus_code','nickname','phone']);
        $shop = $this->container->get(ShopService::class)->shopInfoByWhere(['shop_id' => $shopId], ['shop_no','shop_name']);
        $list = $this->queryActivityList('1', '1', '年度账单分享礼', 1, 50);
        if (!empty($list['data']['activityInfo']) && isset($list['data']['activityInfo'])){
            $fActivityId = array_column($list['data']['activityInfo'],'fActivityId')[0];
            $coupon = $this->queryTicketAndPackage($fActivityId, $member->kz_cus_code, 1, 50);
            if ($coupon['code'] == 0) {
                return $coupon;
            } else {
                // 一键领取优惠券
                foreach ($coupon['data']['activityInfo'] as $k => $v){
                    for ($i = 0; $i < $v['fEachNum']; $i++){
                        $res = $this->receiveCoupon($member, $shop, $fActivityId, (string)$v['fDrawCouponId'], $v['fCouponCode']);
                    }
                }
                return ['code' => 1, 'msg' => $res['msg'] == '领取数量已达上限!' ? '已领取':'领取成功', 'data' => []];
            }
        }
        return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => '没有可领取的优惠券'];
    }

    protected function transform(array $data, ?array $couponInfo){
        return array_map(
            fn(&$v) => $v = [
                'name' => $v['ticketTypeName'],
                'category' => $v['ticketDeductType'],
                'scope' => $v['fUseRange'],
                'apply_type' => $v['ticketType'],
                'expire' => empty($v['fStartTime']) ? '' : $v['fStartTime']. ' - '. $v['fEndTime'],
                'effective_day' => $v['fDays'] ?? 0,
                'value' => ($couponInfo and $couponInfo['subcode'] == $v['ticketTypeCode']) ? $couponInfo['value']:bcmul((string)$v['fFee'],'100'),
                'minimum_amt' => $v['fLowMoney'],
                'ticket_code' => $v['ticketCode'],
                'subcode' => $v['ticketTypeCode']
            ], $data);
    }

    protected function transformData(array $ticketList){
        return array_map(
            fn(&$v) => $v = [
                'name' => $v['fName'],
                'category' => $v['fType'],
                'scope' => $v['fUseRange'],
                'apply_type' => $v['fUseType'],
                'expire' => empty($v['fStartTime']) ? '' : $v['fStartTime']. ' - '. $v['fEndTime'],
                'effective_day' => $v['fDays'] ?? 0,
                'value' => bcmul((string)$v['fFee'],'100'),
                'allow_take_number' => $v['fEachNum'],
                'draw_coupon_id' => $v['fDrawCouponId'],
                'subcode' => $v['fCouponCode'],
                'coupon_activity_id' => $v['fActivityId'],
                'stock' => $v['fTotalStock'],
                'use_time' => $v['fUseTime'],
                'usable' => $v['fEffectDays']
            ], $ticketList);
    }

    protected function getGoodsInfo(array $goodsListArr, string $lsyShopNo, $orderSource){
        list($actGoodsIds, $basicGoodsIds, $seckillKey) = [[],[],[]];
        foreach ($goodsListArr as $k => $v){
            $v['activity_goods_id'] > 0 ? array_push($actGoodsIds, $v['activity_goods_id']):array_push($basicGoodsIds, $v['goods_id']);
            if ($v['group_id'] == 4) array_push($seckillKey, "{$v['goods_id']}:{$v['activity_goods_id']}");
        }
        $act_goods = $this->activityGoods($actGoodsIds);
        $basic_goods = $this->basicGoods($basicGoodsIds);
        if($orderSource == 0) $basic_goods = $this->getPosPrice($lsyShopNo, $basic_goods);

        $merge =  array_merge($act_goods, $basic_goods);
        foreach ($seckillKey as $k => $v){
            $costKey = explode(':', $v)[0] . ':0';
            if (array_key_exists($costKey, $merge)) $merge[$costKey]['price_selling'] = $merge[$v]['costprice'];
        }
        return $merge;
    }

    protected function getPosPrice(string $lsy_shop_no, array $goods){
        $pos_price = $this->container->get(LsyShopGoodsPriceService::class)
            ->shopGoodsPriceByScheme($lsy_shop_no, array_column($goods,'goods_crm_code'));
        $pos_price_arr = collect($pos_price)->keyBy('crm_goods_id')->toArray();
        array_walk($goods, function(&$item) use ($pos_price_arr){
            $price = $item['group_id'] == 2 ? $item['member_price']:$item['price_selling'];
            if ($item['read_pos_price'] == 1){
                $posSellingPrice = array_key_exists($item['goods_crm_code'], $pos_price_arr) ?
                    $pos_price_arr[$item['goods_crm_code']]['price'] : $price;
            }else{
                $posSellingPrice = $price;
            }
            $item['price_selling'] = $item['scant_id'] == 1 ?
                bcmul(bcdiv($posSellingPrice,'1000',6),(string)$item['ratio'],2) : $posSellingPrice;
        });
        return $goods;
    }

    protected function transformGoodsDataPushKz(array $goodsInput, array $goodsRaw, $entrustId){
        list($goods, $orderGoodsMoney) = [[],[]];
        foreach ($goodsInput as $k => $v) {
            $key = is_numeric($entrustId) ? "{$v['goods_id']}":"{$v['goods_id']}:{$v['activity_goods_id']}";
            $kz_goods_id = !empty($goodsRaw[$key]['kz_goods_id']) ? $goodsRaw[$key]['kz_goods_id'] : $v['goods_id'];
            $goods[$k]['fShelfNum'] = $v['kz_self_num'] ?? '';
            $goods[$k]['goodsId'] = $kz_goods_id;
            $goods[$k]['typeId'] = $goodsRaw[$key]['kz_type_id'] ??0;
            $goods[$k]['goodsName'] = $goodsRaw[$key]['title'];
            $goods[$k]['goodsPrice'] = bcmul((string)$goodsRaw[$key]['price_selling'],'100');
            $goods[$k]['goodsNum'] = $v['goods_num'];
            $goods[$k]['allPrice'] = bcmul($goods[$k]['goodsPrice'], (string)$v['goods_num']);
            array_push($orderGoodsMoney, $goods[$k]['allPrice']);
        }
        return ['goods' => $goods, 'amount' => $orderGoodsMoney];
    }

    protected function entrustOrder($entrustId){
        return EntrustOrderGoodsModel::query()
            ->select(['goods_id','kz_goods_id','kz_type_id','title','dis_unit_price as price_selling','kz_self_num'])
            ->where('entrust_order_id', $entrustId)
            ->get()->keyBy('goods_id')->toArray();
    }

    protected function activityGoods(array $actGoodsIds){
        return ActivityGoodsModel::query()
            ->from('store_activity_goods as ag')
            ->leftJoin('store_goods as g','ag.goods_id','=','g.id')
            ->select(['ag.goods_id','ag.goods_title as title','ag.costprice','ag.price_selling','g.kz_type_id','g.kz_goods_id','ag.id as activity_goods_id'])
            ->whereIn('ag.id', $actGoodsIds)
            ->get()->keyBy(function ($item) {
                return "{$item['goods_id']}:{$item['activity_goods_id']}";
            })->toArray();
    }

    protected function basicGoods(array $basicGoodsIds){
        return GoodsModel::query()
            ->from('store_goods as g')
            ->leftJoin('store_goods_list as gl', 'g.id', '=', 'gl.goods_id')
            ->select(['gl.goods_id','g.title','g.group_id','g.scant_id','g.ratio','g.kz_type_id','g.kz_goods_id','g.read_pos_price','g.goods_crm_code','gl.price_selling','gl.member_price'])
            ->whereIn('g.id', $basicGoodsIds)
            ->get()->keyBy(function ($item){
                return "{$item['goods_id']}:0";
            })->toArray();
    }

}
